﻿using System.Web;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using TSharp.Core.Web;

namespace System
{
    /// <summary>
    /// AOP容器上下文
    /// <para>by tangjingbo at 2009-11-4 14:37</para>
    /// </summary>
    public sealed class AopContext : IDisposable
    {
        #region KEYS

        /// <summary>
        /// 系统容器key
        /// </summary>
        public const string SYSTEMKEY = "CONTAINER_SYSTEM";
        /// <summary>
        /// 会话容器KEY
        /// </summary>
        public const string SESSIONKEY = "CONTAINER_SESSION";

        /// <summary>
        /// 请求容器key
        /// </summary>
        public const string REQUSETKEY = "CONTAINER_REQUEST";

        /// <summary>
        /// 系统容器名称
        /// </summary>
        public static string SYSTEMCONTAINERNAME = "system";

        /// <summary>
        /// 会话容器名称
        /// </summary>
        public static string SESSIONCONTAINERNAME = "session";

        /// <summary>
        /// 请求容器名称
        /// </summary>
        public static string REQUESTCONTAINERNAME = "request";
        #endregion

        private static readonly object lockhelper = new object();

        private static readonly AopContext _ctx = new AopContext();
      
        private static UnityConfigurationSection _unitySection;

        private static IUnityContainer _rootContainer;

        static AopContext()
        {
            InitSystem(true);
        }

        /// <summary>
        /// 
        /// <para>by tangjingbo at 2009-10-22 17:48</para>
        /// </summary>
        private AopContext()
        {
        }

        /// <summary>
        /// aop上下文
        /// </summary>
        public static AopContext Current
        {
            get { return _ctx; }
        }

        /// <summary>
        /// 系统级别容器
        /// <para>by tangjingbo at 2009-11-4 14:37</para>
        /// </summary>
        /// <value></value>
        public IUnityContainer Root
        {
            get
            {

                if (_rootContainer == null)
                {
                    InitSystem(false);
                }
                return _rootContainer;
            }
        }

        /// <summary>
        /// unity配置节点
        /// <para>by tangjingbo at 2009-11-4 14:38</para>
        /// </summary>
        /// <value></value>
        public static UnityConfigurationSection UnitySection
        {
            get
            {
                if (_unitySection != null)
                {
                    return _unitySection;
                }
                _unitySection = WebConfigUtil.GetSection<UnityConfigurationSection>("unity");
                return _unitySection;
            }
        }

        private static void InitSystem(bool breakAllSession)
        {
            lock (lockhelper)
            {
                if (breakAllSession)
                {
                    if (_rootContainer != null)
                        _rootContainer.Dispose();
                    
                }

                _unitySection = null;
                _rootContainer = new UnityContainer();

                UnityConfigurationSection section = UnitySection;
                UnityContainerElement container = section.Containers[SYSTEMCONTAINERNAME];
                if (container != null)
                    container.Configure(_rootContainer);
            }
        }

        /// <summary>
        /// 重新启动系统
        /// </summary>
        public void Reset(bool breakAllSession)
        {
            InitSystem(breakAllSession);
        }

        /// <summary>
        /// 会话级别容器
        /// <para>by tangjingbo at 2009-11-4 14:36</para>
        /// </summary>
        /// <value></value>
        public IUnityContainer OfSession(HttpContextBase ctx)
        {
            var _session = (IUnityContainer) ctx.Session[SESSIONKEY];
            if (_session == null)
            {
                _session = Root.CreateChildContainer();
                UnityConfigurationSection section = UnitySection;
                UnityContainerElement containerconfig = section.Containers[SESSIONCONTAINERNAME];
                if (containerconfig != null)
                    containerconfig.Configure(_session);
                ctx.Session[SESSIONKEY] = _session;
            }
            return _session;
        }

        /// <summary>
        /// 请求级别容器
        /// <para>by tangjingbo at 2009-11-4 14:36</para>
        /// </summary>
        /// <value></value>
        public IUnityContainer OfRequest(HttpContextBase ctx)
        {
            var request = (IUnityContainer) ctx.Items[REQUSETKEY];
            if (request == null)
            {
                request = OfSession(ctx).CreateChildContainer();
                //   _request.RegisterType<ISituation<TMessage>, SituationImpl<TMessage>>(new ContainerControlledLifetimeManager());
                UnityConfigurationSection section = UnitySection;
                UnityContainerElement config = section.Containers[REQUESTCONTAINERNAME];
                if (config != null)
                    config.Configure(request);
                ctx.Items[REQUSETKEY] = request;
            }
            return request;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <returns></returns>
        [Obsolete("已过时")]
        public static TService GetService<TService>()
        {
            return Current.OfRequest(new HttpContextWrapper(HttpContext.Current)).Resolve<TService>();
        }

        /// <summary>
        /// Gets the session.
        /// </summary>
        /// <param name="ctx">The CTX.</param>
        /// <returns></returns>
        public static IUnityContainer GetSession(HttpContextBase ctx)
        {
            return Current.OfSession(ctx);
        }

        /// <summary>
        /// Gets the session.
        /// </summary>
        /// <param name="ctx">The CTX.</param>
        /// <returns></returns>
        public static IUnityContainer GetSession(HttpContext ctx)
        {
            return GetSession(new HttpContextWrapper(ctx));
        }

        /// <summary>
        /// Gets the request.
        /// </summary>
        /// <param name="ctx">The CTX.</param>
        /// <returns></returns>
        public static IUnityContainer GetRequest(HttpContextBase ctx)
        {
            return Current.OfRequest(ctx);
        }

        /// <summary>
        /// Gets the request.
        /// </summary>
        /// <param name="ctx">The CTX.</param>
        /// <returns></returns>
        public static IUnityContainer GetRequest(HttpContext ctx)
        {
            return GetRequest(new HttpContextWrapper(ctx));
        }

        #region IDisposable 成员

        /// <summary>
        /// 
        /// <para>by tangjingbo at 2009-11-4 14:38</para>
        /// </summary>
        public void Dispose()
        {
            if (_rootContainer != null)
            {
                _rootContainer.Dispose();
            }
        }

        /// <summary>
        /// 
        /// <para>by tangjingbo at 2009-11-4 14:38</para>
        /// </summary>
        ~AopContext()
        {
            //try
            //{
            //    Dispose();
            //}
            //catch (Exception ex)
            //{
            //    EventLog log;
            //    using (log = new EventLog { Source = "Aop应用程序" })
            //    {
            //        log.WriteEntry(ex.ToString(), EventLogEntryType.Error);
            //    }
            //    //  log.WriteEntry("处理信息2", EventLogEntryType.Information);
            //    //throw ex;
            //}
        }

        #endregion
    }
}